package org.zhtkj.web.endpoint;

import static org.zhtkj.web.jt808.common.JT808MessageCode.CAN总线数据上传;
import static org.zhtkj.web.jt808.common.JT808MessageCode.事件报告;
import static org.zhtkj.web.jt808.common.JT808MessageCode.位置信息查询应答;
import static org.zhtkj.web.jt808.common.JT808MessageCode.位置信息汇报;
import static org.zhtkj.web.jt808.common.JT808MessageCode.信息点播取消;
import static org.zhtkj.web.jt808.common.JT808MessageCode.删除圆形区域;
import static org.zhtkj.web.jt808.common.JT808MessageCode.删除多边形区域;
import static org.zhtkj.web.jt808.common.JT808MessageCode.删除矩形区域;
import static org.zhtkj.web.jt808.common.JT808MessageCode.删除路线;
import static org.zhtkj.web.jt808.common.JT808MessageCode.多媒体事件信息上传;
import static org.zhtkj.web.jt808.common.JT808MessageCode.多媒体数据上传;
import static org.zhtkj.web.jt808.common.JT808MessageCode.存储多媒体数据检索应答;
import static org.zhtkj.web.jt808.common.JT808MessageCode.定位数据批量上传;
import static org.zhtkj.web.jt808.common.JT808MessageCode.平台通用应答;
import static org.zhtkj.web.jt808.common.JT808MessageCode.提问应答;
import static org.zhtkj.web.jt808.common.JT808MessageCode.摄像头立即拍摄命令应答;
import static org.zhtkj.web.jt808.common.JT808MessageCode.数据上行透传;
import static org.zhtkj.web.jt808.common.JT808MessageCode.数据压缩上报;
import static org.zhtkj.web.jt808.common.JT808MessageCode.查询终端参数应答;
import static org.zhtkj.web.jt808.common.JT808MessageCode.清空区域和路线;
import static org.zhtkj.web.jt808.common.JT808MessageCode.电子运单上报;
import static org.zhtkj.web.jt808.common.JT808MessageCode.电子运单查询应答;
import static org.zhtkj.web.jt808.common.JT808MessageCode.电话回拨;
import static org.zhtkj.web.jt808.common.JT808MessageCode.终端RSA公钥;
import static org.zhtkj.web.jt808.common.JT808MessageCode.终端上传音视频资源列表;
import static org.zhtkj.web.jt808.common.JT808MessageCode.终端升级结果通知;
import static org.zhtkj.web.jt808.common.JT808MessageCode.终端心跳;
import static org.zhtkj.web.jt808.common.JT808MessageCode.终端注册;
import static org.zhtkj.web.jt808.common.JT808MessageCode.终端注册应答;
import static org.zhtkj.web.jt808.common.JT808MessageCode.终端注销;
import static org.zhtkj.web.jt808.common.JT808MessageCode.终端通用应答;
import static org.zhtkj.web.jt808.common.JT808MessageCode.终端鉴权;
import static org.zhtkj.web.jt808.common.JT808MessageCode.行驶记录仪参数下传命令;
import static org.zhtkj.web.jt808.common.JT808MessageCode.行驶记录仪数据上传;
import static org.zhtkj.web.jt808.common.JT808MessageCode.行驶记录仪数据采集命令;
import static org.zhtkj.web.jt808.common.JT808MessageCode.设置圆形区域;
import static org.zhtkj.web.jt808.common.JT808MessageCode.设置多边形区域;
import static org.zhtkj.web.jt808.common.JT808MessageCode.设置电话本;
import static org.zhtkj.web.jt808.common.JT808MessageCode.设置矩形区域;
import static org.zhtkj.web.jt808.common.JT808MessageCode.设置路线;
import static org.zhtkj.web.jt808.common.JT808MessageCode.车外屏信息查询应答;
import static org.zhtkj.web.jt808.common.JT808MessageCode.车辆控制应答;
import static org.zhtkj.web.jt808.common.JT808MessageCode.载重监测校准数据上报;
import static org.zhtkj.web.jt808.common.JT808MessageCode.驾驶员身份信息查询应答;
import static org.zhtkj.web.jt808.common.JT808MessageCode.驾驶员身份信息采集上报;
import static org.zhtkj.web.jt808.common.JT808MessageCode.驾驶员身份验证信息上报;
import static org.zhtkj.web.jt808.common.JT808MessageCode.查询终端音视频属性响应;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.zhtkj.framework.annotation.Endpoint;
import org.zhtkj.framework.annotation.Mapping;
import org.zhtkj.framework.codec.MessageEncoder;
import org.zhtkj.framework.commons.transform.BCD8421Operator;
import org.zhtkj.framework.commons.transform.BitOperator;
import org.zhtkj.framework.message.PackageData;
import org.zhtkj.framework.message.SyncFuture;
import org.zhtkj.framework.session.MessageManager;
import org.zhtkj.framework.session.Session;
import org.zhtkj.framework.session.SessionManager;
import org.zhtkj.web.config.Charsets;
import org.zhtkj.web.dao.AuthInfoMapper;
import org.zhtkj.web.dao.HistoryMapper;
import org.zhtkj.web.dao.RegisterInfoMapper;
import org.zhtkj.web.dao.RuntimeAttrMapper;
import org.zhtkj.web.dao.RuntimeInfoMapper;
import org.zhtkj.web.dao.StatusInfoMapper;
import org.zhtkj.web.jt808.common.JT808MessageCode;
import org.zhtkj.web.jt808.dto.Authentication;
import org.zhtkj.web.jt808.dto.CANBusReport;
import org.zhtkj.web.jt808.dto.CameraShotReply;
import org.zhtkj.web.jt808.dto.CommonResult;
import org.zhtkj.web.jt808.dto.DriverIdentityInfoQueryReply;
import org.zhtkj.web.jt808.dto.DriverIdentityInfoReport;
import org.zhtkj.web.jt808.dto.DriverIdentityInfoVerifyReport;
import org.zhtkj.web.jt808.dto.DrivingRecordReport;
import org.zhtkj.web.jt808.dto.ElectronWayBillQueryReply;
import org.zhtkj.web.jt808.dto.ElectronWayBillReport;
import org.zhtkj.web.jt808.dto.EventReport;
import org.zhtkj.web.jt808.dto.GZIPPack;
import org.zhtkj.web.jt808.dto.LoadAdjustDataReport;
import org.zhtkj.web.jt808.dto.MediaDataQueryReply;
import org.zhtkj.web.jt808.dto.MediaDataReport;
import org.zhtkj.web.jt808.dto.MediaEventReport;
import org.zhtkj.web.jt808.dto.MediaPlaybackReply;
import org.zhtkj.web.jt808.dto.MediaPropReply;
import org.zhtkj.web.jt808.dto.MessageSubOperate;
import org.zhtkj.web.jt808.dto.ParameterQueryReply;
import org.zhtkj.web.jt808.dto.PassthroughPack;
import org.zhtkj.web.jt808.dto.PositionAttribute;
import org.zhtkj.web.jt808.dto.PositionReply;
import org.zhtkj.web.jt808.dto.PositionReport;
import org.zhtkj.web.jt808.dto.PositionReportBatch;
import org.zhtkj.web.jt808.dto.PositionReportBatch.PositionReportBatchData;
import org.zhtkj.web.jt808.dto.QuestionMessageReply;
import org.zhtkj.web.jt808.dto.RSAPack;
import org.zhtkj.web.jt808.dto.Register;
import org.zhtkj.web.jt808.dto.RegisterResult;
import org.zhtkj.web.jt808.dto.ScreenInfoQueryReply;
import org.zhtkj.web.jt808.dto.TerminalUpgradeNotify;
import org.zhtkj.web.jt808.dto.basics.Header;
import org.zhtkj.web.model.AuthInfo;
import org.zhtkj.web.model.HistoryAttr;
import org.zhtkj.web.model.HistoryInfo;
import org.zhtkj.web.model.HistoryWarn;
import org.zhtkj.web.model.RegisterInfo;
import org.zhtkj.web.model.RuntimeInfo;
import org.zhtkj.web.model.RuntimeInfoAttr;
import org.zhtkj.web.model.StatusInfo;
import org.zhtkj.web.utils.JT808ProtocolUtils;
import org.zhtkj.web.utils.MediaPacketUtils;
import org.zhtkj.web.utils.MediaPacketUtils.ActionInfo;
import org.zhtkj.web.utils.MediaPacketUtils.PacketInfo;

import com.baomidou.mybatisplus.core.conditions.query.EmptyWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;

@Endpoint
@Component
public class JT808Endpoint {

    private static final Logger logger = LoggerFactory.getLogger(JT808Endpoint.class.getSimpleName());

    private MessageManager messageManager = MessageManager.INSTANCE;
    
    @Value("${media.file.uri}")
    private String uri;
    
    @Autowired
    private SessionManager sessionManager;

    @Autowired
    private MessageEncoder<Header> encoder;

    @Autowired
    private RegisterInfoMapper registerInfoMapper;
    
    @Autowired
    private AuthInfoMapper authInfoMapper;
    
    @Autowired
    private HistoryMapper historyMapper;
    
    @Autowired
    private StatusInfoMapper statusInfoMapper;
    
    @Autowired
    private RuntimeInfoMapper runtimeInfoMapper;
    
    @Autowired
    private RuntimeAttrMapper runtimeAttrMapper;
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    @Autowired
    private JT808EndpointService endpointService;
    
    
    public Object send(PackageData<Header> packageData) {
        return send(packageData, true);
    }

    public Object send(PackageData<Header> packageData, boolean hasReplyFlowIdId) {
        Header header = packageData.getHeader();
        String terminalPhone = header.getTerminalPhone();
        Session session = sessionManager.findByTerminalId(terminalPhone);
        if (session != null) {
            header.setFlowId(session.currentFlowId());
            //对消息包进行转义
            ByteBuf buf = JT808ProtocolUtils.doEscape4Send(encoder.encodeAll(packageData));
            logger.info("{}out,hex:{}\n{}" + (hasReplyFlowIdId ? "" : "\n"), JT808MessageCode.getMessageDesc(header.getType()), "7e" + ByteBufUtil.hexDump(buf) + "7e", packageData);
            ByteBuf allResultBuf = Unpooled.wrappedBuffer(Unpooled.wrappedBuffer(new byte[]{0x7e}), buf, Unpooled.wrappedBuffer(new byte[]{0x7e}));
            session.getChannel().writeAndFlush(allResultBuf);
            if (hasReplyFlowIdId) {
            	String key = terminalPhone + (hasReplyFlowIdId ? header.getFlowId() : "");
                SyncFuture<?> receive = messageManager.receive(key);
                try {
                    return receive.get(10, TimeUnit.SECONDS);
                } catch (InterruptedException e) {
                    messageManager.remove(key);
                    e.printStackTrace();
                }
            } else {
            	return null;
            }
        }
        return null;
    }
    
    @Mapping(types = 终端通用应答, desc = "终端通用应答")
    public void 终端通用应答(CommonResult packageData) {
        Header header = packageData.getHeader();
        String terminalPhone = header.getTerminalPhone();
        Integer replyId = packageData.getFlowId();
        messageManager.put(terminalPhone + replyId, packageData);
    }

    @Mapping(types = 查询终端参数应答, desc = "查询终端参数应答/查询指定终端参数应答")
    public void 查询终端参数应答(ParameterQueryReply packageData) {
        Header header = packageData.getHeader();
        String terminalPhone = header.getTerminalPhone();
        Integer replyId = packageData.getFlowId();
        messageManager.put(terminalPhone + replyId, packageData);
    }

    @Mapping(types = {位置信息查询应答, 车辆控制应答}, desc = "位置信息查询应答/车辆控制应答")
    public void 位置信息查询应答(PositionReply packageData) {
        Header header = packageData.getHeader();
        String terminalPhone = header.getTerminalPhone();
        Integer replyId = packageData.getFlowId();
        messageManager.put(terminalPhone + replyId, packageData);
    }

    @Mapping(types = 终端RSA公钥, desc = "终端RSA公钥")
    public void 终端RSA公钥(RSAPack packageData) {
        Header header = packageData.getHeader();
        String terminalPhone = header.getTerminalPhone();
        messageManager.put(terminalPhone, packageData);
    }

    @Mapping(types = 存储多媒体数据检索应答, desc = "存储多媒体数据检索应答")
    public void 存储多媒体数据检索应答(MediaDataQueryReply packageData, Session session) {
        Header header = packageData.getHeader();
        String terminalPhone = header.getTerminalPhone();
        Integer replyId = packageData.getFlowId();
        messageManager.put(terminalPhone + replyId, packageData);
    }

	@Mapping(types = 终端心跳, desc = "终端心跳")
    public CommonResult 终端心跳(PackageData<Header> packageData, Session session) {
		//验证session信息
		Object isAuthenticated = redisTemplate.opsForHash()
				.get("session:" + packageData.getHeader().getTerminalPhone(), "isAuthenticated");
    	if (isAuthenticated == null) {
    		return null;
    	}
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        CommonResult result = new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
        return result;
    }

    @Mapping(types = 终端注册, desc = "终端注册")
    public RegisterResult 终端注册(Register packageData, Session session) {
        Header header = packageData.getHeader();
        Integer resultCode;
        String authCode = UUID.randomUUID().toString();
        AuthInfo authInfo = authInfoMapper.selectOne(new QueryWrapper<AuthInfo>()
        		.eq("license_plate", packageData.getLicensePlate())
        		.eq("terminal_Id", header.getTerminalPhone()));
        if (authInfo != null) {
        	resultCode = RegisterResult.Success;
        	//保存或更新车辆注册信息
            RegisterInfo regInfo = registerInfoMapper.selectById(packageData.getLicensePlate());
            if (regInfo != null) {
            	authCode = regInfo.getAuthCode();
            	BeanUtils.copyProperties(packageData, regInfo);
            	regInfo.setTerminalId(header.getTerminalPhone());
            	registerInfoMapper.updateById(regInfo);
            } else {
            	regInfo = new RegisterInfo();
            	BeanUtils.copyProperties(packageData, regInfo);
            	regInfo.setTerminalId(header.getTerminalPhone());
            	regInfo.setAuthCode(authCode);
            	registerInfoMapper.insert(regInfo);
            }
        } else {
        	resultCode = RegisterResult.VehicleNotFound;
        }
        Header resultHeader = new Header(终端注册应答, session.currentFlowId(), header.getTerminalPhone());
        RegisterResult result = new RegisterResult(resultHeader, resultCode, authCode);
        return result;
    }

	@Mapping(types = 终端注销, desc = "终端注销")
    public CommonResult 终端注销(PackageData<Header> packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        //删除车辆注册信息
        RegisterInfo registerInfo = new RegisterInfo();
        registerInfo.setTerminalId(header.getTerminalPhone());
        registerInfoMapper.delete(new EmptyWrapper<RegisterInfo>().eq("terminal_phone", header.getTerminalPhone()));
        CommonResult result = new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
        return result;
    }

	@Mapping(types = 终端鉴权, desc = "终端鉴权")
    public CommonResult 终端鉴权(Authentication packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        Integer resultCode; 
        //查询终端注册信息表并鉴权
        RegisterInfo regInfo = registerInfoMapper.selectOne(new QueryWrapper<RegisterInfo>()
        		.eq("terminal_id", header.getTerminalPhone()));
		String key = "session:" + packageData.getHeader().getTerminalPhone();
		HashOperations<String, Object, Object> ops = redisTemplate.opsForHash();
		ops.put(key, "sessionId", session.getId());
        if (regInfo != null) {
    		resultCode = CommonResult.Success;
    		//添加session信息
    		ops.put(key, "isAuthenticated", true);
    		ops.put(key, "licensePlate", regInfo.getLicensePlate());
        } else {
    		//添加session信息
    		ops.put(key, "isAuthenticated", false);
        	resultCode = CommonResult.Fail;
        }
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), resultCode);
    }

	@Mapping(types = 位置信息汇报, desc = "位置信息汇报")
    public CommonResult 位置信息汇报(PositionReport packageData, Session session) {
		//验证session信息
		String key = "session:" + packageData.getHeader().getTerminalPhone();
		HashOperations<String, Object, Object> ops = redisTemplate.opsForHash();
		String licensePlate = (String) ops.get(key, "licensePlate");
		if (licensePlate == null) {
			return null;
		}
    	try {
			//保存位置信息
			HistoryInfo hisInfo = new HistoryInfo();
			hisInfo.setLicensePlate(licensePlate);
			hisInfo.setTerminalId(packageData.getHeader().getTerminalPhone());
			hisInfo.setLatitude(packageData.getLatitude()/1000000D);
			hisInfo.setLongitude(packageData.getLongitude()/1000000D);
			hisInfo.setAltitude(packageData.getAltitude());
			hisInfo.setSpeed(packageData.getSpeed());
			hisInfo.setDirection(packageData.getDirection());
			String[] status = BitOperator.get32BitString(packageData.getStatus()).split("");
			hisInfo.setLockStatus(Integer.parseInt(status[25]));
			hisInfo.setLimitStatus(Integer.parseInt(status[26]));
			hisInfo.setLimitLift(Integer.parseInt(status[27]));
			hisInfo.setLoadStatus(Integer.parseInt(status[28]));
			hisInfo.setBoxStatus(Integer.parseInt(status[29]));
			hisInfo.setLiftStatus(Integer.parseInt(status[30]));
			hisInfo.setMaintainType(Integer.parseInt(status[31]));
			hisInfo.setStatusMark(packageData.getStatus());
			hisInfo.setWarnMark(packageData.getWarningMark());
			DateTime reportTime = DateTime.parse("20" + packageData.getReportTime(), DateTimeFormat.forPattern("yyyyMMddHHmmss"));
			hisInfo.setReportTime(reportTime.toDate());
			hisInfo.setInsertTime(new Date());
			hisInfo.setYearMonth(reportTime.toString("yyyyMM"));
			//分析车辆状态变化，如果有状态变化则将状态变化信息存入数据库
			HistoryInfo lastHisInfo = session.getHistoryInfo();
			if (lastHisInfo != null) {
				StatusInfo statusInfo = new StatusInfo();
				if (lastHisInfo.getLoadStatus() == 1 && hisInfo.getLoadStatus() == 0) {
					statusInfo.setOpen(1);
				}
				if (lastHisInfo.getLoadStatus() == 0 && hisInfo.getLoadStatus() == 1) {
					statusInfo.setHeavy(1);
				}
				if (lastHisInfo.getBoxStatus() == 0 && hisInfo.getBoxStatus() == 1) {
					statusInfo.setOpen(1);
				}
				if (lastHisInfo.getBoxStatus() == 1 && hisInfo.getBoxStatus() == 0) {
					statusInfo.setClose(1);
				}
				if (lastHisInfo.getLiftStatus() == 0 && hisInfo.getLiftStatus() == 1) {
					statusInfo.setUp(1);
				}
				if (lastHisInfo.getLiftStatus() == 1 && hisInfo.getLiftStatus() == 0) {
					statusInfo.setFlat(1);
				}
				if (statusInfo.isInsert()) {
					statusInfo.setLicensePlate(hisInfo.getLicensePlate());
					statusInfo.setTerminalId(hisInfo.getTerminalId());
					statusInfo.setLatitude(hisInfo.getLatitude());
					statusInfo.setLongitude(hisInfo.getLongitude());
					statusInfo.setAltitude(hisInfo.getAltitude());
					statusInfo.setSpeed(hisInfo.getSpeed());
					statusInfo.setDirection(hisInfo.getDirection());
					statusInfo.setReportTime(hisInfo.getReportTime());
					statusInfoMapper.insert(statusInfo);
				}
			}
			//将位置信息放入session
			session.setHistoryInfo(hisInfo);
			//附加信息解析
			HistoryAttr hisAttr = new HistoryAttr();
			hisAttr.setTerminalId(packageData.getHeader().getTerminalPhone());
			for (PositionAttribute attr: packageData.getPositionAttributes()) {
				Integer id = attr.getId();
				byte[] byteValue = attr.getBytesValue();
				if (id == 0xE5) { //设备连接状态标志位
					hisAttr.setConnectMark(BitOperator.fourBytesToInteger(byteValue));
				} else if (id == 0xED) { //水泥罐车罐体转向标志
					hisAttr.setTurnMark((int) byteValue[0]);
				} else if (id == 0xEE) { //水泥罐车转速
					hisAttr.setRevSpeed(BitOperator.twoBytesToInteger(byteValue));
				} else if (id == 0xF3) { //实际载重
					hisAttr.setLoadSize(BitOperator.twoBytesToInteger(byteValue));
				} else if (id == 0xF5) { //车辆VIN
					hisAttr.setVehicleVin(new String(byteValue, Charsets.GBK));
				} else if (id == 0xF6) { //can总线信息
					hisAttr.setMileage(BitOperator.fourBytesToInteger(Arrays.copyOfRange(byteValue, 0, 4)));
					hisAttr.setOilUse(BitOperator.fourBytesToInteger(Arrays.copyOfRange(byteValue, 4, 8)));
					hisAttr.setOilRest((int) byteValue[8]);
					hisAttr.setOilInst(BitOperator.twoBytesToInteger(Arrays.copyOfRange(byteValue, 9, 11)));
					hisAttr.setCanSpeed(BitOperator.twoBytesToInteger(Arrays.copyOfRange(byteValue, 11, 13)));
					hisAttr.setRotateSpeed(BitOperator.twoBytesToInteger(Arrays.copyOfRange(byteValue, 13, 15)));
					hisAttr.setTorque(BitOperator.fourBytesToInteger(Arrays.copyOfRange(byteValue, 15, 19)));
					hisAttr.setVoltage(BitOperator.twoBytesToInteger(Arrays.copyOfRange(byteValue, 19, 21)));
					hisAttr.setBrake((int) byteValue[21]);
					hisAttr.setCoolantTemp((int) byteValue[22]);
				} else if (id == 0xF7) { //紧急状态上报
					hisAttr.setUrgentStatus((int) byteValue[0]);
					hisAttr.setUrgentStatusTime(DateTime.parse("20" + BCD8421Operator.bcd2String(Arrays.copyOfRange(byteValue, 1, 7)), 
							DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate());
				}
			}
			
			//附加信息报警解析
			HistoryWarn hisWarn = new HistoryWarn();
			hisWarn.setHistoryWarnId(hisInfo.getHistoryInfoId());
			hisWarn.setLicensePlate(licensePlate);
			hisWarn.setTerminalId(packageData.getHeader().getTerminalPhone());
			hisWarn.setReportTime(hisInfo.getReportTime());
			hisWarn.setPowerBreak(Integer.parseInt(BitOperator.get32BitString(packageData.getWarningMark()).split("")[8]));
			String[] connectBit = null;
			for (PositionAttribute attr: packageData.getPositionAttributes()) {
				byte[] byteValue = attr.getBytesValue();
				//设备连接状态解析
				if (attr.getId() == 0xE5) {
					connectBit = BitOperator.get32BitString(BitOperator.fourBytesToInteger(byteValue)).split("");
					hisWarn.setLoadOff(Integer.parseInt(connectBit[19]));
					hisWarn.setLiftOff(Integer.parseInt(connectBit[20]));
					hisWarn.setBoxOff(Integer.parseInt(connectBit[21]));
				}
				//报警解析
				if (attr.getId() == 0xE1) {
					String[] warnMark = BitOperator.get32BitString(BitOperator.fourBytesToInteger(byteValue)).split("");
					hisWarn.setRapidAcc(Integer.parseInt(warnMark[0]));
					hisWarn.setRapidSlow(Integer.parseInt(warnMark[1]));
					hisWarn.setRapidChange(Integer.parseInt(warnMark[2]));
					hisWarn.setRapidTurn(Integer.parseInt(warnMark[3]));
					hisWarn.setImpact(Integer.parseInt(warnMark[17]));
					hisWarn.setOverload(Integer.parseInt(warnMark[18]));
					hisWarn.setHeavySpeed(Integer.parseInt(warnMark[19]));
					hisWarn.setVioUnload(Integer.parseInt(warnMark[20]));
					hisWarn.setHeavyBoxOpen(Integer.parseInt(warnMark[21]));
					hisWarn.setBadDrive(Integer.parseInt(warnMark[22]));
					hisWarn.setHeavyEnter(Integer.parseInt(warnMark[23]));
				}
			}
			historyMapper.insertHistoryInfo(hisInfo);
			hisAttr.setHistoryAttrId(hisInfo.getHistoryInfoId());
			hisAttr.setYearMonth(hisInfo.getYearMonth());
			historyMapper.insertHistoryAttr(hisAttr);
			hisWarn.setHistoryWarnId(hisInfo.getHistoryInfoId());
			hisWarn.setYearMonth(hisInfo.getYearMonth());
			
			//要过滤的报警
			endpointService.handlerWarnInfo(hisInfo, hisWarn, connectBit);
			//所有报警
			if (hisWarn.isValid()) {
				historyMapper.insertHistoryWarn(hisWarn);
			}
			//更新实时位置信息表
			RuntimeInfo runtimeInfo = new RuntimeInfo();
			runtimeInfo.setLicensePlate(licensePlate);
			runtimeInfo.setTerminalId(hisInfo.getTerminalId());
			runtimeInfo.setLatitude(hisInfo.getLatitude());
			runtimeInfo.setLongitude(hisInfo.getLongitude());
			runtimeInfo.setAltitude(hisInfo.getAltitude());
			runtimeInfo.setSpeed(hisInfo.getSpeed());
			runtimeInfo.setDirection(hisInfo.getDirection());
			runtimeInfo.setLockStatus(hisInfo.getLockStatus());
			runtimeInfo.setLimitStatus(hisInfo.getLimitStatus());
			runtimeInfo.setLimitLift(hisInfo.getLimitLift());
			runtimeInfo.setLoadStatus(hisInfo.getLoadStatus());
			runtimeInfo.setBoxStatus(hisInfo.getBoxStatus());
			runtimeInfo.setLiftStatus(hisInfo.getLiftStatus());
			runtimeInfo.setMaintainType(hisInfo.getMaintainType());
			runtimeInfo.setStatusMark(hisInfo.getStatusMark());
			runtimeInfo.setWarnMark(hisInfo.getWarnMark());
			runtimeInfo.setReportTime(hisInfo.getReportTime());
			runtimeInfo.setUpdateTime(hisInfo.getInsertTime());
			runtimeInfo.setOnlineStatus(1);
			if (runtimeInfoMapper.updateById(runtimeInfo) == 0) {
				runtimeInfoMapper.insert(runtimeInfo);
			}
			//更新实时位置附加属性表
			RuntimeInfoAttr runtimeInfoAttr = new RuntimeInfoAttr();
			runtimeInfoAttr.setLicensePlate(licensePlate);
			runtimeInfoAttr.setConnectMark(hisAttr.getConnectMark());
			runtimeInfoAttr.setTurnMark(hisAttr.getTurnMark());
			runtimeInfoAttr.setRevSpeed(hisAttr.getRevSpeed());
			runtimeInfoAttr.setLoadSize(hisAttr.getLoadSize());
			runtimeInfoAttr.setVehicleVin(hisAttr.getVehicleVin());
			runtimeInfoAttr.setMileage(hisAttr.getMileage());
			runtimeInfoAttr.setOilUse(hisAttr.getOilUse());
			runtimeInfoAttr.setOilRest(hisAttr.getOilRest());
			runtimeInfoAttr.setOilInst(hisAttr.getOilInst());
			runtimeInfoAttr.setCanSpeed(hisAttr.getCanSpeed());
			runtimeInfoAttr.setRotateSpeed(hisAttr.getRotateSpeed());
			runtimeInfoAttr.setTorque(hisAttr.getTorque());
			runtimeInfoAttr.setVoltage(hisAttr.getVoltage());
			runtimeInfoAttr.setBrake(hisAttr.getBrake());
			runtimeInfoAttr.setCoolantTemp(hisAttr.getCoolantTemp());
			runtimeInfoAttr.setUrgentStatus(hisAttr.getUrgentStatus());
			runtimeInfoAttr.setUrgentStatusTime(hisAttr.getUrgentStatusTime());
			if (runtimeAttrMapper.updateById(runtimeInfoAttr) == 0) {
				runtimeAttrMapper.insert(runtimeInfoAttr);
			}
		} catch (Exception e) {
			logger.error("{}，位置信息处理错误：\n", licensePlate, e);
			e.printStackTrace();
		}
        //响应终端
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        CommonResult result = new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
        return result;
    }

    @Mapping(types = 事件报告, desc = "事件报告")
    public CommonResult 事件报告(EventReport packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }

    @Mapping(types = 提问应答, desc = "提问应答")
    public CommonResult 提问应答(QuestionMessageReply packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }

    @Mapping(types = 信息点播取消, desc = "信息点播/取消")
    public CommonResult 信息点播取消(MessageSubOperate packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }

    @Mapping(types = 电话回拨, desc = "电话回拨")
    public CommonResult 电话回拨(PackageData<Header> packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }

    @Mapping(types = 设置电话本, desc = "设置电话本")
    public CommonResult 设置电话本(PackageData<Header> packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }

    @Mapping(types = 设置圆形区域, desc = "设置圆形区域")
    public CommonResult 设置圆形区域(PackageData<Header> packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }

    @Mapping(types = 删除圆形区域, desc = "删除圆形区域")
    public CommonResult 删除圆形区域(PackageData<Header> packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }

    @Mapping(types = 设置矩形区域, desc = "设置矩形区域")
    public CommonResult 设置矩形区域(PackageData<Header> packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }

    @Mapping(types = 删除矩形区域, desc = "删除矩形区域")
    public CommonResult 删除矩形区域(PackageData<Header> packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }

    @Mapping(types = 设置多边形区域, desc = "设置多边形区域")
    public CommonResult 设置多边形区域(PackageData<Header> packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }

    @Mapping(types = 删除多边形区域, desc = "删除多边形区域")
    public CommonResult 删除多边形区域(PackageData<Header> packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }

    @Mapping(types = 设置路线, desc = "设置路线")
    public CommonResult 设置路线(PackageData<Header> packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }

    @Mapping(types = 删除路线, desc = "删除路线")
    public CommonResult 删除路线(PackageData<Header> packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }

    @Mapping(types = 清空区域和路线, desc = "清空区域和路线")
    public CommonResult 清空区域和路线(PackageData<Header> packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }
    
    @Mapping(types = 行驶记录仪数据采集命令, desc = "行驶记录仪数据采集命令")
    public CommonResult 行驶记录仪数据采集命令(PackageData<Header> packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }

    @Mapping(types = 行驶记录仪数据上传, desc = "行驶记录仪数据上传")
    public CommonResult 行驶记录仪数据上传(DrivingRecordReport packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }

    @Mapping(types = 行驶记录仪参数下传命令, desc = "行驶记录仪参数下达命令")
    public CommonResult 行驶记录仪参数下传命令(PackageData<Header> packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }

    @Mapping(types = 电子运单上报, desc = "电子运单上报")
    public CommonResult 电子运单上报(ElectronWayBillReport packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }

    @Mapping(types = 驾驶员身份信息采集上报, desc = "驾驶员身份信息采集上报")
    public CommonResult 驾驶员身份信息采集上报(DriverIdentityInfoReport packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }

	@Mapping(types = 定位数据批量上传, desc = "定位数据批量上传")
    public CommonResult 定位数据批量上传(PositionReportBatch packageData, Session session) {
    	//验证session信息
		String key = "session:" + packageData.getHeader().getTerminalPhone();
		HashOperations<String, Object, Object> ops = redisTemplate.opsForHash();
		String licensePlate = (String) ops.get(key, "licensePlate");
		if (licensePlate == null) {
			return null;
		}
    	//保存批量位置信息
    	for (PositionReportBatchData prbd: packageData.getPositionReportBatchDataList()) {
    		PositionReport position = prbd.getPositionReport();
    		//保存位置信息
            HistoryInfo hisInfo = new HistoryInfo();
            hisInfo.setLicensePlate(licensePlate);
            hisInfo.setTerminalId(packageData.getHeader().getTerminalPhone());
            hisInfo.setLatitude(position.getLatitude()/1000000D);
            hisInfo.setLongitude(position.getLongitude()/1000000D);
            hisInfo.setAltitude(position.getAltitude());
            hisInfo.setSpeed(position.getSpeed());
            hisInfo.setDirection(position.getDirection());
            String[] status = BitOperator.get32BitString(position.getStatus()).split("");
            hisInfo.setLockStatus(Integer.parseInt(status[25]));
            hisInfo.setLimitStatus(Integer.parseInt(status[26]));
            hisInfo.setLimitLift(Integer.parseInt(status[27]));
            hisInfo.setLoadStatus(Integer.parseInt(status[28]));
            hisInfo.setBoxStatus(Integer.parseInt(status[29]));
            hisInfo.setLiftStatus(Integer.parseInt(status[30]));
            hisInfo.setMaintainType(Integer.parseInt(status[31]));
            hisInfo.setStatusMark(position.getStatus());
            hisInfo.setWarnMark(position.getWarningMark());
            DateTime reportTime = DateTime.parse("20" + position.getReportTime(), DateTimeFormat.forPattern("yyyyMMddHHmmss"));
            hisInfo.setReportTime(reportTime.toDate());
            hisInfo.setInsertTime(new Date());
            hisInfo.setYearMonth(reportTime.toString("yyyyMM"));
            //附加信息解析
            HistoryAttr hisAttr = new HistoryAttr();
            hisAttr.setHistoryAttrId(hisInfo.getHistoryInfoId());
            hisAttr.setTerminalId(packageData.getHeader().getTerminalPhone());
            for (PositionAttribute attr: position.getPositionAttributes()) {
            	Integer id = attr.getId();
            	byte[] byteValue = attr.getBytesValue();
            	if (id == 0xE5) { //设备连接状态标志位
            		hisAttr.setConnectMark(BitOperator.fourBytesToInteger(byteValue));
            	} else if (id == 0xED) { //水泥罐车罐体转向标志
            		hisAttr.setTurnMark((int) byteValue[0]);
            	} else if (id == 0xEE) { //水泥罐车转速
            		hisAttr.setRevSpeed(BitOperator.twoBytesToInteger(byteValue));
            	} else if (id == 0xF3) { //实际载重
            		hisAttr.setLoadSize(BitOperator.twoBytesToInteger(byteValue));
            	} else if (id == 0xF5) { //车辆VIN
        			hisAttr.setVehicleVin(new String(byteValue, Charsets.GBK));
            	} else if (id == 0xF6) { //can总线信息
        			hisAttr.setMileage(BitOperator.fourBytesToInteger(Arrays.copyOfRange(byteValue, 0, 4)));
        			hisAttr.setOilUse(BitOperator.fourBytesToInteger(Arrays.copyOfRange(byteValue, 4, 8)));
        			hisAttr.setOilRest((int) byteValue[8]);
        			hisAttr.setOilInst(BitOperator.twoBytesToInteger(Arrays.copyOfRange(byteValue, 9, 11)));
        			hisAttr.setCanSpeed(BitOperator.twoBytesToInteger(Arrays.copyOfRange(byteValue, 11, 13)));
        			hisAttr.setRotateSpeed(BitOperator.twoBytesToInteger(Arrays.copyOfRange(byteValue, 13, 15)));
        			hisAttr.setTorque(BitOperator.fourBytesToInteger(Arrays.copyOfRange(byteValue, 15, 19)));
        			hisAttr.setVoltage(BitOperator.twoBytesToInteger(Arrays.copyOfRange(byteValue, 19, 21)));
        			hisAttr.setBrake((int) byteValue[21]);
        			hisAttr.setCoolantTemp((int) byteValue[22]);
            	} else if (id == 0xF7) { //紧急状态上报
    				hisAttr.setUrgentStatus((int) byteValue[0]);
    				hisAttr.setUrgentStatusTime(DateTime.parse("20" + BCD8421Operator.bcd2String(Arrays.copyOfRange(byteValue, 1, 7)), 
    						DateTimeFormat.forPattern("yyyyMMddHHmmss")).toDate());
            	}
            }
            //附加信息报警解析
            HistoryWarn hisWarn = new HistoryWarn();
            hisWarn.setHistoryWarnId(hisInfo.getHistoryInfoId());
            hisWarn.setLicensePlate(licensePlate);
            hisWarn.setTerminalId(packageData.getHeader().getTerminalPhone());
            hisWarn.setReportTime(hisInfo.getReportTime());
            for (PositionAttribute attr: position.getPositionAttributes()) {
            	//终端主电源掉电解析
            	hisWarn.setPowerBreak(Integer.parseInt(BitOperator.get32BitString(position.getWarningMark()).split("")[8]));
            	byte[] byteValue = attr.getBytesValue();
            	//设备连接状态解析
            	if (attr.getId() == 0xE5) {
            		String[] connectBit = BitOperator.get32BitString(BitOperator.fourBytesToInteger(byteValue)).split("");
            		hisWarn.setLoadOff(Integer.parseInt(connectBit[19]));
            		hisWarn.setLiftOff(Integer.parseInt(connectBit[20]));
            		hisWarn.setBoxOff(Integer.parseInt(connectBit[21]));
            	}
            	//报警解析
            	if (attr.getId() == 0xE1) {
            		String[] warnMark = BitOperator.get32BitString(BitOperator.fourBytesToInteger(byteValue)).split("");
            		hisWarn.setRapidAcc(Integer.parseInt(warnMark[0]));
            		hisWarn.setRapidSlow(Integer.parseInt(warnMark[1]));
            		hisWarn.setRapidChange(Integer.parseInt(warnMark[2]));
            		hisWarn.setRapidTurn(Integer.parseInt(warnMark[3]));
            		hisWarn.setImpact(Integer.parseInt(warnMark[17]));
            		hisWarn.setOverload(Integer.parseInt(warnMark[18]));
            		hisWarn.setHeavySpeed(Integer.parseInt(warnMark[19]));
            		hisWarn.setVioUnload(Integer.parseInt(warnMark[20]));
            		hisWarn.setHeavyBoxOpen(Integer.parseInt(warnMark[21]));
            		hisWarn.setBadDrive(Integer.parseInt(warnMark[22]));
            	}
            }
            historyMapper.insertHistoryInfo(hisInfo);
            hisAttr.setHistoryAttrId(hisInfo.getHistoryInfoId());
            hisAttr.setYearMonth(hisInfo.getYearMonth());
            historyMapper.insertHistoryAttr(hisAttr);
            hisWarn.setHistoryWarnId(hisInfo.getHistoryInfoId());
            hisWarn.setYearMonth(hisInfo.getYearMonth());
            //所有报警
            if (hisWarn.isValid()) {
            	historyMapper.insertHistoryWarn(hisWarn);
            }
    	}
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }
    
    @Mapping(types = CAN总线数据上传, desc = "CAN总线数据上传")
    public CommonResult CAN总线数据上传(CANBusReport packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }

    @Mapping(types = 多媒体事件信息上传, desc = "多媒体事件信息上传")
    public CommonResult 多媒体事件信息上传(MediaEventReport packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }

    @Mapping(types = 多媒体数据上传, desc = "多媒体数据上传")
    public CommonResult mediaDataReport(MediaDataReport packageData, Session session) {
    	if (packageData.getHeader().isHasSubPackage() == true) {
    		String key = packageData.getHeader().getTerminalPhone();
    		if (MediaPacketUtils.getPacket(key) == null) {
    			MediaPacketUtils.putPacket(key, new PacketInfo(new DateTime(), new MediaDataReport[packageData.getHeader().getTotalSubPackage()]));
    		}
    		MediaPacketUtils.getPacket(key).getPackageDatas()[packageData.getHeader().getSubPackageSeq() - 1] = packageData;
    	}
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }

/*    @Mapping(types = 多媒体数据上传应答, desc = "多媒体数据上传应答")
    public CommonResult 多媒体数据上传应答(PackageData<Header> packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, 多媒体数据上传应答, session.currentFlowId(), CommonResult.Success);
    }*/

    @Mapping(types = 终端上传音视频资源列表, desc = "终端上传音视频资源列表")
    public CommonResult 终端上传音视频资源列表(MediaPlaybackReply packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(终端上传音视频资源列表, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }
    

    @Mapping(types = 摄像头立即拍摄命令应答, desc = "摄像头立即拍摄命令应答")
    public CommonResult 摄像头立即拍摄命令应答(CameraShotReply packageData, Session session) {
    	String packetKey = packageData.getHeader().getTerminalPhone();
    	String actionKey = packageData.getHeader().getTerminalPhone() + ":" + packageData.getFlowId();
    	if (packageData.getResult() == 0 && packageData.getTotal() == 1 && packageData.getMediaDataList().size() > 0) {
			PacketInfo packetInfo = MediaPacketUtils.getPacket(packetKey);
			if (packetInfo  != null && packetInfo.getPackageDatas()[0] != null) {
				byte[] firstPacket = ((MediaDataReport) packetInfo.getPackageDatas()[0]).getPacket();
				List<Byte> finalBytes = new ArrayList<Byte>();
				for (byte bt: Arrays.copyOfRange(firstPacket, 36, firstPacket.length)) {
					finalBytes.add(bt);
				}
    	        for (int i = 1; i < packetInfo.getPackageDatas().length; i++) {
    	        	if (packetInfo.getPackageDatas()[i] != null) {
    	        		MediaDataReport mediaDataReport = (MediaDataReport) packetInfo.getPackageDatas()[i];
    	        		for (byte bt: mediaDataReport.getPacket()) {
    	        			finalBytes.add(bt);
    	        		}
    	        	} else {
    	        		logger.info(packageData.getHeader().getTerminalPhone() + "，多媒体数据包缺失");
    	        	}
    	        }
    	        String mediaFormat = null;
    	        String event = null;
            	switch (firstPacket[5]) {
        			case 0:
        				mediaFormat = "jpg";
        				break;
        			case 1:
        				mediaFormat = "tif";
        				break;
        			case 2:
        				mediaFormat = "mp3";
        				break;
        			case 3:
        				mediaFormat = "wav";
        				break;
        			case 4:
        				mediaFormat = "wmv";
        				break;
        		}
            	switch (firstPacket[6]) {
        			case 0:
        				event = "cameraShot";
        				break;
        			case 1:
        				event = "taskAction";
        				break;
        			case 2:
        				event = "robWarn";
        				break;
        			case 3:
        				event = "impact";
        				break;
        			case 100:
        				event = "overload";
        				break;
        			case 101:
        				event = "vioload";
        				break;
        			case 102:
        				event = "heavybox";
        				break;
        			case 120:
        				event = "noIdentity";
        				break;
        			case 121:
        				event = "badDrive";
        				break;
        		}
            	if (mediaFormat != null && event != null) {
            		ActionInfo actionInfo = MediaPacketUtils.getAction(actionKey);
            		String fileName =  null;
            		if (actionInfo == null || actionInfo.getActionId() == null) {
            			fileName = packageData.getHeader().getTerminalPhone() + "_"  + packageData.getMediaDataList().get(0).getId();
            		} else {
            			fileName = actionInfo.getActionId().toString();
            		}
            		File path = new File(uri + File.separator + event + File.separator + actionInfo.getReceiveTime().toString("yyyy"));
            		File file = new File(path.getPath() + File.separator + fileName + "." + mediaFormat);
                    FileOutputStream fos = null;
                    try {
                    	if (!path.exists()) {
                    		path.mkdirs();
                    	}
                    	if (file.exists()) {
                         	file.delete();
                        }
                        if (!file.exists()) {
                        	file.createNewFile();
                        }
        				fos = new FileOutputStream(file);
        				byte[] bts = new byte[finalBytes.size()];
        				for (int i = 0; i < finalBytes.size(); i++) {
        					bts[i] = finalBytes.get(i);
        				}
        				fos.write(bts);
        				fos.flush();
        			} catch (FileNotFoundException e) {
        				e.printStackTrace();
        			} catch (IOException e) {
        				e.printStackTrace();
        			} finally {
        				if (fos != null) {
        					try {
        						fos.close();
        					} catch (IOException e) {
        						e.printStackTrace();
        					}
        				}
        			}
            	}
			}
    	}
		MediaPacketUtils.removeActionInfo(actionKey);
		MediaPacketUtils.removePacketInfo(packetKey);
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }
    
    @Mapping(types = 数据上行透传, desc = "数据上行透传")
    public CommonResult passthrough(PassthroughPack packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }

    @Mapping(types = 数据压缩上报, desc = "数据压缩上报")
    public CommonResult gzipPack(GZIPPack packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }

    @Mapping(types = 终端升级结果通知, desc = "终端升级结果通知")
    public CommonResult 终端升级结果通知(TerminalUpgradeNotify packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }
    
    @Mapping(types = 电子运单查询应答, desc = "数据压缩上报")
    public CommonResult 电子运单查询应答(ElectronWayBillQueryReply packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }
    
    @Mapping(types = 车外屏信息查询应答, desc = "车外屏信息查询应答")
    public CommonResult 车外屏信息查询应答(ScreenInfoQueryReply packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }
    
    @Mapping(types = 驾驶员身份信息查询应答, desc = "驾驶员身份信息查询应答")
    public CommonResult 驾驶员身份信息查询应答(DriverIdentityInfoQueryReply packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }
    
    @Mapping(types = 驾驶员身份验证信息上报, desc = "驾驶员身份验证信息上报")
    public CommonResult 驾驶员身份验证信息上报(DriverIdentityInfoVerifyReport packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }
    
    @Mapping(types = 载重监测校准数据上报, desc = "载重监测校准数据上报")
    public CommonResult 载重监测校准数据上报(LoadAdjustDataReport packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }
    
    @Mapping(types = 查询终端音视频属性响应, desc = "查询终端音视频属性响应")
    public CommonResult 查询终端音视频属性响应(MediaPropReply packageData, Session session) {
        Header header = packageData.getHeader();
        Header resultHeader = new Header(平台通用应答, session.currentFlowId(), header.getTerminalPhone());
        return new CommonResult(resultHeader, header.getFlowId(), header.getType(), CommonResult.Success);
    }
}